//------------------------------------------------------------------------------
// Class: gewWorldCamera inherited from gewCamera

function gewWorldCamera() {
  gewCamera.call(this);
  
  this.m_fov = 60.0;
  this.m_aspect = 1.0;
  this.m_near = 10.0;
  this.m_far = 1000.0;
  
  this.m_desired_fov = this.m_fov;
  this.m_desired_pos = new gewVec3(0.0, 0.0, 1.0);
  this.m_up = new gewVec3(0.0, 1.0, 0.0);
  this.m_look_at_position = new gewVec3(0.0, 0.0, 0.0);
  
  //this.m_desired_orient = new gewVec3(-GEW_MATH_PI / 2.0, 0.0, 0.0);
}
extend2(gewWorldCamera, gewCamera);

gewWorldCamera.prototype.calcZoom = function()
{
  var factor = 1;
  if (this.last_factor) {
    factor = this.m_zoom_factor / this.last_factor;
    this.last_factor = this.m_zoom_factor;
  } else {
    factor = this.m_zoom_factor;
    this.last_factor = this.m_zoom_factor;
  }
  
  this.m_desired_fov = this.m_fov;
  
  var pos = this.m_desired_pos.sub(this.m_look_at_position);
  pos = pos.mulScalar(factor);
  this.m_desired_pos = this.m_look_at_position.add(pos);
  
  this.setCameraFlag(CAMERA_UPDATE_PROJ_MATRIX | CAMERA_UPDATE_VIEW_MATRIX, true);
}

gewWorldCamera.prototype.resetAttribute = function() {
  this.m_fov = 60.0;
  this.m_desired_fov = this.m_fov;
  this.m_desired_pos = new gewVec3(0.0, 0.0, 1.0);
  this.m_up = new gewVec3(0.0, 1.0, 0.0);
  this.m_look_at_position = new gewVec3(0.0, 0.0, 0.0);
  this.m_near = 10.0;
  this.m_far = 1000.0;
  this.setCameraFlag(CAMERA_UPDATE_PROJ_MATRIX | CAMERA_UPDATE_VIEW_MATRIX, true);
}
/**
 * gewWorldCamera.prototype.pan
 * @param from: 2D point in camera viewport
 * @param to  : 2D point in camera viewport
 */
gewWorldCamera.prototype.pan = function(from, to) {
  var forward = this.m_look_at_position.sub(this.m_desired_pos);
  
  var length = forward.getLength();
  
  //this.m_look_at_position = this.m_desired_pos.add(this.m_forward.mulScalar((this.m_near + this.m_far) / 2));
  //var fovy = 2 * Math.atan(this.m_zoom_factor * Math.tan(this.m_fov*GEW_MATH_DEGREE_TO_RADIAN / 2));
  //fovy /= GEW_MATH_DEGREE_TO_RADIAN;
  //if (fovy < 0.0) fovy = 180 + fovy;
  
  var fovy = this.m_desired_fov;
  
  var height = 2 * length * 
                Math.tan(fovy / 2 * GEW_MATH_DEGREE_TO_RADIAN);
  
  var cy = this.m_viewport_size.y;
  
  var dx = to.x - from.x;
  dx = dx / cy * height;
  
  var dy = to.y - from.y;
  dy = dy / cy * height;
  
  this.m_right.normalize();
  this.m_up.normalize();
  
  var dx_vec = this.m_right.mulScalar(-dx);
  var dy_vec = this.m_up.mulScalar(dy);
  
  var dif_vec = dx_vec.add(dy_vec); // dif_vec = dx_vec + dy_vec
  //this.m_desired_pos = this.m_desired_pos.add(dif_vec);
  this.m_look_at_position = this.m_look_at_position.add(dif_vec);
  
  this.setCameraFlag(CAMERA_UPDATE_VIEW_MATRIX, true);
}

/**
 * gewWorldCamera.prototype.pan
 * @param from: 2D point in camera viewport
 * @param to  : 2D point in camera viewport
 */
gewWorldCamera.prototype.rotateCam = function(from, to) {
  var dx = to.x - from.x;
  var dy = to.y - from.y;
  var width = this.m_viewport_size.x;
  var height = this.m_viewport_size.y;
  dx = dx / width;
  dy = dy / height;
  
  dx = dx * 2 * GEW_MATH_PI;
  dy = dy * 2 * GEW_MATH_PI;
  
  var pitch_matrix = gewMat4.getRotate(this.m_right, -dy);
  var yaw_matrix = gewMat4.getRotate(this.m_up, -dx);
  
  pitch_matrix.mul(yaw_matrix, gewRegMat0);
  
  var forward = this.m_desired_pos.sub(this.m_look_at_position);
  
  forward = gewRegMat0.mulVec3(forward);
  
  this.m_desired_pos = this.m_look_at_position.add(forward);
  
  //var pos = this.m_desired_pos;
  //var up = this.m_up;
  //var right = this.m_right;
  //var center = this.m_desired_pos.add(this.m_forward.mulScalar((this.m_near + this.m_far) / 2));
  
  //gewAffineTransform.rotatePoint(pos, center, up, dx);
  //gewAffineTransform.rotatePoint(pos, center, right, -dy);
  
  //this.m_desired_pos = pos;
  
  // var forward = center - pos;
  // var angle = forward.angleFrom(this.m_forward);
  //this.m_yaw -= dx / GEW_MATH_DEGREE_TO_RADIAN;
  //this.m_pitch += dy / GEW_MATH_DEGREE_TO_RADIAN;
  
  this.setCameraFlag(CAMERA_UPDATE_VIEW_MATRIX, true);
}

gewWorldCamera.prototype.zoom = function(delta){
  var factor = this.getZoomFactor();
  var org_factor = factor;
  if (factor < 1.0) {
    factor = 1 / factor;
  }
    
  if (delta < 0) { // zoom out
    if (delta < -1) {
      delta = -1;
    }
    if (org_factor <= 1.0) {
      factor -= delta;
      factor = 1.0 / factor;
    } else {
      factor += delta;
    }
      
    //if (factor < 0.025) {
    //  factor = 0.025;
    //}

    this.setZoomFactor(factor);
  } else { // zoom in
    if (delta > 1) {
      delta = 1;
    }
    if (org_factor < 1.0) {
      factor -= delta;
      factor = 1 / factor;
    } else {
      factor += delta;
    }
      
    //if (factor > 40.0) {
    //  factor = 40.0;
    //}
      
    this.setZoomFactor(factor);
  }
  
  this.calcZoom();
};

gewWorldCamera.prototype.onMouseUp = function(e) 
{
  this.mousekey = -1;
}

gewWorldCamera.prototype.onMouseDown = function(e)
{
  this.mousekey = e.button;
  this.start_point = new gewVec2(e.canvasX, e.canvasY);
}

gewWorldCamera.prototype.onMouseMove = function(e)
{
  var cur_point = new gewVec2(e.canvasX, e.canvasY);
  if (this.mousekey == GEW_MOUSE_LEFT && e.ctrlKey == true) {
    this.pan(this.start_point, cur_point);
    this.setUp( new gewVec3(0,1,0));
    //this.moveBySide(cur_point.sub(this.start_point));
  }
  if (this.mousekey == GEW_MOUSE_LEFT && e.altKey == true) {
    this.rotateCam(this.start_point, cur_point);
    this.setUp( new gewVec3(0,1,0));
  }
  this.start_point = cur_point;
}

gewWorldCamera.prototype.onMouseWheel = function(e)
{
  var delta = 0;

  if (e.wheelDelta) {
    delta = event.wheelDelta / 120; 
    if (window.opera) delta = -delta;
  } else if (event.detail) {
    delta = -event.detail / 3;
  }
  
  //this.zoom(delta);  
  this.forward(delta *1.5);
}

gewWorldCamera.prototype.onKeyDown = function(e) {

}

gewWorldCamera.prototype.onKeyPress = function(e)
{
  this.step = this.step ? this.step : 3.0;
  
  switch (e.keychar) {
    case 'w':
      if (this.step < 10.0) {
        this.step += 1.0;
      }
      
      this.up(this.step);
      break;
      
    case 's':
      if (this.step < 10.0) {
        this.step += 1.0;
      }
      
      this.up(-this.step);
      break;
      
    case 'a':
      if (this.step < 10.0) {
        this.step += 1.0;
      }
      
      this.side(-this.step);
      break;
      
    case 'd':
      if (this.step < 10.0) {
        this.step += 1.0;
      }
      
      this.side(this.step);
      break;
      
    default:
      break;
  }
}

gewWorldCamera.prototype.onKeyUp = function(e)
{
  this.step = 3.0;
}


